#include "../include/GameMap.hh"
#include "../include/Room.hh"
#include <iostream>
#include <cstdlib>
#include <ctime>

namespace Game {
    // Constructor: Initialize 3x3 map with random rooms
    GameMap::GameMap() : playerPos_({1, 1}) {
        rooms_.resize(3, std::vector<Room>(3));
        bool bossPlaced = false;
        bool healingPlaced = false;
        bool trapPlaced = false;

        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                Room::Type type = Room::NORMAL;
                if (i == 1 && j == 1) {
                    type = Room::START; // The center is the initial room
                } else {
                    // Forced to generate a boss room and a healing room
                    if (!bossPlaced && rand() % 5 == 0) { 
                        type = Room::BOSS;
                        bossPlaced = true;
                    } else if (!healingPlaced && rand() % 10 == 0) {
                        type = Room::HEALING;
                        healingPlaced = true;
                    }else if(!trapPlaced && rand() % 5 == 0){
                        type = Room::TRAP;
                        trapPlaced = true;
                    }
                }
                rooms_[i][j] = Room(type, "Room (" + std::to_string(i) + "," + std::to_string(j) + ")");
            }
        }
        //Make sure there is at least one boss room and one treatment room
        if (!bossPlaced) rooms_[0][2] = Room(Room::BOSS, "Boss Room");
        if (!healingPlaced) rooms_[2][1] = Room(Room::HEALING, "Healing Room");
        if (!trapPlaced) {
            int i = rand() % 3;
            int j = rand() % 3;
            if (i != 1 || j != 1) { 
                rooms_[i][j] = Room(Room::TRAP, "Trap Room");
            }
        }
        // Connect rooms
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                Room* north = (i > 0) ? &rooms_[i-1][j] : nullptr;
                Room* east = (j < 2) ? &rooms_[i][j+1] : nullptr;
                Room* south = (i < 2) ? &rooms_[i+1][j] : nullptr;
                Room* west = (j > 0) ? &rooms_[i][j-1] : nullptr;
                rooms_[i][j].connect(north, east, south, west);
            }
        }

        currentRoom_ = &rooms_[1][1]; // Start at center
    }

    // Copy constructor
    GameMap::GameMap(const GameMap& other) 
        : rooms_(other.rooms_), 
          currentRoom_(other.currentRoom_),
          playerPos_(other.playerPos_) {}

    // Assignment operator
    GameMap& GameMap::operator=(const GameMap& other) {
        if (this != &other) {
            rooms_ = other.rooms_;
            currentRoom_ = other.currentRoom_;
            playerPos_ = other.playerPos_;
        }
        return *this;
    }

    // Move player in direction (north/south/east/west)
    bool GameMap::movePlayer(const std::string& direction) {
        int newRow = playerPos_.first;
        int newCol = playerPos_.second;

        if (direction == "north") newRow--;
        else if (direction == "south") newRow++;
        else if (direction == "east") newCol++;
        else if (direction == "west") newCol--;
        else return false;

        // Check boundaries
        if (newRow < 0 || newRow >= 3 || newCol < 0 || newCol >= 3) {
            return false;
        }

        playerPos_ = {newRow, newCol};
        currentRoom_ = &rooms_[newRow][newCol];
        return true;
    }

    // Print ASCII map with symbols
    void GameMap::printMap() const {
        std::cout << "Map:\n";
        for (int i = 0; i < 3; ++i) {
            for (int j = 0; j < 3; ++j) {
                if (i == playerPos_.first && j == playerPos_.second) {
                    std::cout << "[X]"; // Player position
                } else {
                    switch (rooms_[i][j].getType()) {
                        case Room::BOSS: std::cout << "[B]"; break;
                        case Room::HEALING: std::cout << "[H]"; break;
                        case Room::START: std::cout << "[S]"; break;
                        default: std::cout << "[ ]"; // Trap/Combat rooms
                    }
                }
            }
            std::cout << "\n";
        }
    }

    // Check if current room is Boss room
    bool GameMap::isInBossRoom() const {
        return currentRoom_->getType() == Room::BOSS;
    }

    // Getters
    Room* GameMap::getCurrentRoom() const { 
        return currentRoom_; 
    }
}